#include "fw_hal.h"

// Define Address
#ifndef NOX_KIT_ADDR
#define NOX_KIT_ADDR 0x66
#endif

// Define Pin
#define TEMP_PIN          GPIO_Pin_4
#define PHOTO_PIN         GPIO_Pin_5

// Define ADC Channel
#define TEMP_ADC_CHANNEL  0x04
#define PHOTO_ADC_CHANNEL 0x05

// ADC data: 0 for TEMP, 1 for PHOTO
#define TEMP_TARGET       0
#define PHOTO_TARGET      1

uint8_t adc_target;
__IDATA uint16_t adc_dat[2];

// Read ADC at Channel
INTERRUPT(ADC_Routine, EXTI_VectADC) {
  ADC_ClearInterrupt();

  // Write ADC data
  adc_dat[adc_target] = ADC_RESL;
  adc_dat[adc_target] |= (ADC_RES & 0x0f) << 8;

  // Switch ADC Channel
  adc_target = (adc_target + 1) & 0x1;
  if (adc_target == TEMP_TARGET) {
    ADC_SetChannel(TEMP_ADC_CHANNEL);
  } else {
    ADC_SetChannel(PHOTO_ADC_CHANNEL);
  }
  ADC_Start();
}
// UART COMMAND CODES
#define NIL        0x0
#define UART_TEMP  'T'
#define UART_PHOTO 'P'

// UART Send Message
#define SEND(c)    UART1_TxHex(c >> 8); UART1_TxHex(c & 0xff);

INTERRUPT(UART1_Routine, EXTI_VectUART1) {
  uint8_t c;
  if (RI) {
    UART1_ClearRxInterrupt();
    c = SBUF;
    switch (c) {
    case UART_TEMP:
      SEND(adc_dat[TEMP_TARGET]);
      break;
    case UART_PHOTO:
      SEND(adc_dat[PHOTO_TARGET]);
      break;
    default:
      SEND(0xffff);
      break;
    }
  }
}

// I2C Working States
__BIT waitDeviceAddress;
__BIT waitMemoryAddress;

INTERRUPT(I2C_Routine, EXTI_VectI2C) {
  SFRX_ON();

  if (I2C_IsSlaveStartInterrupt()) {
    I2C_ClearSlaveStartInterrupt();
  } else if (I2C_IsSlaveRecvInterrupt()) {
    I2C_ClearSlaveRecvInterrupt();
    if (waitDeviceAddress) {
      if (I2CRXD == NOX_KIT_ADDR)
      waitDeviceAddress = 0;
    } else if (waitMemoryAddress) {
      waitMemoryAddress = 0;
      I2CTXD = adc_dat[I2CRXD % 2];
    } else {
      // add_queue(I2CRXD);
    }
  } else if (I2C_IsSlaveSendInterrupt()) {
    I2C_ClearSlaveSendInterrupt();
    if (I2C_ReadSlaveAckIn()) {
      I2CTXD = 0xff; // stop sending message
    } else {
      // continue send message
      // I2CTXD = adc_dat[adc_target % 2];
    }
  } else if (I2C_IsSlaveStopInterrupt()) {
    I2C_ClearSlaveStopInterrupt();
    waitDeviceAddress = 1;
    waitMemoryAddress = 1;
  }

  SFRX_OFF();
}

void main(void) {
  // Init Pin
  GPIO_P5_SetMode(TEMP_PIN,  GPIO_Mode_Input_HIP);
  GPIO_P5_SetMode(PHOTO_PIN, GPIO_Mode_Input_HIP);
  // Init UART
  UART1_Config8bitUart(UART1_BaudSource_Timer1, HAL_State_ON, 115200);
  UART1_SetRxState(HAL_State_ON);
  
  EXTI_Global_SetIntState(HAL_State_ON);
  EXTI_UART1_SetIntState(HAL_State_ON);
  
  // Init I2C
  I2C_SetWorkMode(I2C_WorkMode_Slave);
  I2C_SetPort(I2C_AlterPort_P32_P33);
  I2CSLADR = 0x5a;
  
  I2C_ClearAllSlaveInterrupts();
  
  EXTI_I2C_SetSlvStartIntState(HAL_State_ON);
  EXTI_I2C_SetSlvRecvIntState(HAL_State_ON);
  EXTI_I2C_SetSlvSendIntState(HAL_State_ON);
  EXTI_I2C_SetSlvStopIntState(HAL_State_ON);
  EXTI_Global_SetIntState(HAL_State_ON);
  
  waitDeviceAddress = 1;
  waitMemoryAddress = 1;
  
  I2C_SetEnabled(HAL_State_ON);
  adc_target = TEMP_TARGET;
  ADC_SetChannel(TEMP_ADC_CHANNEL);
  
  // ADC Clock = SYSCLK / 2 / (1 + prescaler) = SYSCLK / 4
  ADC_SetClockPrescaler(0x03);
  ADC_SetResultAlignmentRight();
  ADC_SetPowerState(HAL_State_ON);
  EXTI_Global_SetIntState(HAL_State_ON);
  EXTI_ADC_SetIntState(HAL_State_ON);
  
  ADC_Start();
  
  adc_dat[0] = 0x0233;
  adc_dat[1] = 0x0332;

  while (1) ;
}
